home *** CD-ROM | disk | FTP | other *** search
- /*
- Subject: v08i080: Public-domain getpw*(3) routines
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: emoryu1!emoryu2!arnold (Arnold D. Robbins)
- Mod.sources: Volume 8, Issue 80
- Archive-name: getpw
-
- Here is public domain re-implementation of the getpwent(3) routines. I have
- not included a manual page, since every Unix system has one. I also haven't
- even bothered to include a <pwd.h> file; you should be able to use the one
- on your system.
-
- There is one additional routine:
- setpwfile (file)
- char *file;
- which will cause the routines to find password records from a file besides
- /etc/passwd. This is useful should you need to use saved password files,
- for instance in doing Unix accounting, where you wish to keep info around on
- old accounts, but take the old accounts out of the live password file.
- (Can you guess why I just whipped these up?)
-
- To switch files, call setpwfile as the very first thing, or call endpwent(),
- then setpwfile ("/some/file").
-
- Anyway, I hope this is useful to somene out there.
- Arnold Robbins
- arnold@emoryu1.{CSNET, UUCP, ARPA, BITNET}
- */
-
- /* minorly customized by ERS for the MiNT library */
-
- /****************************************************************/
- /* Module name: getpw.c */
- /* Library name: mintlibs for Atari ST */
- /* Author: Hildo Biersma (boender@dutiws.twi.tudelft.nl) */
- /* Date: January 29, 1993 */
- /* Revision: 1 (add password aging, add System V routines, */
- /* include three man pages, add example code) */
- /****************************************************************/
-
- /*
- NAME
- getpw - get name from UID
-
- SYNOPSIS
- #include <pwd.h>
-
- int getpw(int uid, char *buf);
-
- DESCRIPTION
- getpw searches the password file for a user id number that
- equals uid, copies the line of the password file in which uid
- was found into the array pointed to by buf, and returns 0.
- getpw returns non-zero if uid cannot be found.
-
- This routine is included only for compatibility with old UN*X
- systems and should not be used in any new programs; see
- getpwent for routines to use instead.
-
- FILES
- /etc/passwd
-
- SEE ALSO
- getpwent
-
- AUTHOR
- Hildo Biersma, with the help of a UN*X System V man page.
- */
-
- /*
- NAME
- getpwent, getpwuid, getpwnam, setpwent, endpwent,
- fgetpwent, setpwfile - get password file entry
-
- SYNOPSIS
- #include <stdio.h> // Only needed for fgetpwent
- #include <pwd.h>
-
- struct passwd *getpwent(void);
-
- struct passwd *getpwuid(int uid);
-
- struct passwd *getpwnam(const char *name);
-
- void setpwent(void);
-
- void endpwent(void);
-
- struct passwd *fgetpwent(FILE *f);
-
- void setpwfile(const char *name);
-
- DESCRIPTION
- getpwent, getpwuid and getpwnam each returns a pointer to an
- object containing the broken-out fields of a line in the
- /etc/passwd file.
- Each line in the file contains a "passwd" structure, declared
- in the <pwd.h> header file. For the definition of this structure
- and the meaning of the fields, see the <pwd.h> header file.
-
- getpwent when first called returns a pointer to the first
- passwd structure in the file; thereafter, it returns a pointer
- to the next passwd structure in the file; so successive calls
- can be used to search the entire file.
-
- getpwuid searches from the beginning of the file until a
- numerical user ID is found matching uid is found and returns
- a pointer to the particular structure in which it was found.
- Thus, it cannot be found to search for several users having
- duplicate numerical user IDs.
-
- getpwnam searches from the beginning of the file until a
- login name matching name is found and returns a pointer to
- the particular structure in which it was found.
-
- If an EOF or an error is encountered on reading, getpwent,
- getpwuid and getpwnam return a NULL pointer.
-
- A call to setpwent has the effect of rewinding the password
- file to allow repeated searches.
-
- endpwent may be called to close the password file when
- processing is complete.
-
- fgetpwent returns a pointer to the next passwd structure in
- the stream f, which matches the format of /etc/passwd.
-
- setpwfile will set the password file to be read from by all
- the above routines except fgetpwent.
-
- FILES
- /etc/passwd
-
- SEE ALSO
- getlogin, getgrent, putpwent
-
- NOTES
- All information is contained in a static area, so it must
- be copied if it is to be saved.
-
- Password aging is supported.
-
- In order not to suffer from possible future changes in the
- format of the passwd file or in the passwd structure,
- these routines should always be used for reading from file,
- while putpwent should always be used for writing to file.
-
- These routines expect the passwd file to be of type text,
- and can therefore read both DOS and UN*X format files.
-
- AUTHORS
- Arnold D. Robbins - original version
- Eric Smith - adapted for the mintlibs
- Hildo Biersma - included System V routines and password aging
- */
-
- /*
- PASSWORD AGING
-
- DESCRIPTION
- Password aging is in effect for a particular user if his
- encrypted password in the password file is followed by a
- comma and a non-null string of characters from the
- alphabet (., /, 0-9, A-Z, a-z) also used for the encrypted
- password. (Such a string must be introduced in the first
- place by the super-user.)
-
- The first character of the age, M say, denotes the maximum
- number of weeks for which a password is valid. A user who
- attempts to login after his password has expired should be
- forced to supply a new one. The next character, N say,
- denotes the minimum number of weeks which must expire
- before the password may be changed. The remaining characters
- define the week (counted from the beginning of 1970) when
- the password was last changed. (A null string is equivalent
- to zero.) M and N have numerical values in the range 0-63
- that correspond to the 64-character alphabet mentioned
- above (i.e., / = 1 week; z = 63 weeks). If M = N = 0
- (derived from the string . or ..) the user should be forced
- to change his password the next time he logs in (and the
- "age" should disappear from his entry in the password file).
- If N > M (signified, e.g., by the string /.) only the
- super-user should be able to change the password.
-
- SEE ALSO
- a64l, getpwent, putpwent
-
- NOTE
- The compliance with password aging in MiNT is a joke, since
- users are not forced to login. Also, the current login program
- supplied in init(1) does not support password aging. This may
- change in the future.
- */
-
- /*
- FIXME:
- - test *thoroughly*
- - write example code for modifying passwd files, include below
- */
-
- #include <stdio.h>
- #include <pwd.h>
- #include <unistd.h>
- #include <string.h>
- #include <stdlib.h>
- #include <types.h>
-
- static char *pwdfile = "/etc/passwd"; /* default passwd file */
-
- static FILE *fp = NULL;
- static struct passwd curentry; /* static data to return */
-
- static int nextent __PROTO((FILE *fp));
-
- /* Get name from uid */
- int getpw(uid, buf)
- int uid;
- char *buf;
- {
- FILE *pw;
- char line[256]; /* Assume this will always be enough */
- char *ptr;
-
- if ((pw = fopen("/etc/passwd", "rt")) == NULL)
- return(-1); /* Failure: file could not be opened */
-
- line[255] = 0x00;
- while (!feof(pw))
- {
- fgets(line, 255, pw);
- if ((ptr = strchr(line, ':')) != NULL) /* Password field found */
- if ((ptr = strchr(ptr + 1, ':')) != NULL) /* UID field found */
- if (atoi(ptr + 1) == uid)
- {
- strcpy(buf, line);
- return(0); /* Success */
- }
- }
- return(-1); /* Failure */
- } /* End of getpw() */
-
- /* Set the name of the passwd file */
- void setpwfile(cp)
- char *cp;
- {
- endpwent();
- if (cp != NULL)
- pwdfile = cp;
- } /* End of setpwfile() */
-
- /* Rewind the passwd file */
- void setpwent()
- {
- if (fp != NULL)
- rewind(fp);
- else if ((fp = fopen (pwdfile, "rt")) == NULL)
- {
- #ifdef VERBOSE
- fprintf (stderr, "setpwent: %s non-existant or unreadable.\n", pwdfile);
- #endif
- }
- } /* End of setpwent() */
-
- /* End passwd file processing */
- void endpwent()
- {
- if (fp != NULL)
- {
- fclose (fp);
- fp = NULL;
- }
- } /* End of endpwent() */
-
- /* Get the next passwd entry from the passwd file */
- struct passwd *getpwent()
- {
- if (fp == NULL)
- {
- setpwent();
- if (fp == NULL)
- return(NULL);
- }
-
- if (nextent(fp) == 0)
- return(NULL);
- else
- return(&curentry);
- } /* End of getpwent() */
-
- /* Get first passwd entry from file with pw_uid matching uid */
- #ifdef __STDC__
- struct passwd *getpwuid(uid_t uid)
- #else
- struct passwd *getpwuid(uid)
- uid_t uid;
- #endif
- {
- setpwent();
- while (nextent(fp) != 0)
- if (curentry.pw_uid == uid)
- return(&curentry);
-
- return(NULL);
- } /* End of getpwuid() */
-
- /* Get first passwd entry from file with pw_name matching name */
- struct passwd *getpwnam(name)
- const char *name;
- {
- setpwent();
-
- while (nextent(fp) != 0)
- if (strcmp(curentry.pw_name, name) == 0)
- return(&curentry);
-
- return(NULL);
- } /* End of getpwnam() */
-
- /* Read the next password structure from a given file */
- struct passwd *fgetpwent(f)
- FILE *f;
- {
- if (f == NULL)
- return(NULL); /* Failure */
-
- if (nextent(f) != 0)
- return(&curentry); /* Success */
-
- return(NULL); /* Failure */
- } /* End of fgetpwent() */
-
- #if defined(atarist) || defined(__SOZOBON__)
- static char savbuf[256]; /* BUFSIZ seems bigger than necessary! */
- #else
- static char savbuf[BUFSIZ];
- #endif
-
- /* Static function getting next entry from passwd file */
- static int nextent(fp)
- FILE *fp;
- {
- char *cp;
-
- if (fp == NULL)
- {
- setpwent();
- if (fp == NULL)
- return(0);
- }
-
- while (fgets(savbuf, (int)sizeof(savbuf), fp) != NULL)
- {
- curentry.pw_age = NULL;
-
- for (cp = savbuf; ((*cp != 0x00) && (*cp != ':')); cp++)
- ;
- curentry.pw_name = savbuf;
- *cp++ = 0x00;
- curentry.pw_passwd = cp;
- for (; ((*cp != 0x00) && (*cp != ':')); cp++)
- if ((*cp == ',') && (curentry.pw_age == NULL))
- {
- /* Password age field found */
- *cp++ = 0x00;
- curentry.pw_age = cp;
- }
- *cp++ = 0x00;
- curentry.pw_uid = atoi(cp);
- for (; ((*cp != 0x00) && (*cp != ':')); cp++)
- ;
- *cp++ = 0x00;
- curentry.pw_gid = atoi(cp);
- for (; ((*cp != 0x00) && (*cp != ':')); cp++)
- ;
- *cp++ = 0x00;
- curentry.pw_gecos = cp;
- curentry.pw_comment = cp;
- for (; ((*cp != 0x00) && (*cp != ':')); cp++)
- ;
- *cp++ = 0x00;
- curentry.pw_dir = cp;
- for (; ((*cp != 0x00) && (*cp != ':')); cp++)
- if (*cp == '\\')
- *cp = '/';
- *cp++ = 0x00;
- curentry.pw_shell = cp;
- for (; ((*cp != 0x00) && (*cp != ':') && (*cp != '\n')); cp++)
- if (*cp == '\\')
- *cp = '/';
- *cp = 0x00;
- if (curentry.pw_age == NULL)
- curentry.pw_age = cp; /* Don't return NULL, return a null string */
- return(1);
- }
- return(0);
- } /* End of nextent() */
-
- /* Old test program removed - Hildo Biersma */
- #ifdef EXAMPLE
-
- /*
- EXAMPLE PROGRAM
-
- DESCRIPTION
- Read all lines from the password file and print all users
- with password aging info. Also print a description of
- the meaning of the aging information of this user.
-
- AUTHOR
- Hildo Biersma (boender@dutiws.twi.tudelft.nl)
-
- STATUS
- Example code; in the public domain.
- */
-
- #include <support.h>
-
- void main()
- {
- struct passwd *this_entry;
- int max_age, min_age;
- char *ptr, min[2], max[2];
- time_t time;
-
- min[1] = max[1] = 0x00;
- while ((this_entry = getpwent()) != NULL)
- if ((this_entry->pw_age[0]) != 0x00)
- {
- if ((max[0] = this_entry->pw_age[0]) != 0x00)
- {
- max_age = (int)a64l(max);
- if ((min[0] = this_entry->pw_age[1]) != 0x00)
- {
- min_age = (int)a64l(min);
- ptr = this_entry->pw_age + 2;
- time = a64l(ptr) * (3600L * 24 * 7); /* Seconds per week */
- }
- else
- time = 0L;
- }
- else
- {
- min_age = 0;
- time = 0L;
- }
- fprintf(stdout, "Name: %s, UID: %d.\n", this_entry->pw_name,
- this_entry->pw_uid);
- if ((max_age == 0) && (min_age == 0))
- fprintf(stdout, "User should change password on next login.\n\n");
- else if (min_age > max_age)
- fprintf(stdout, "Only super-user may change password.\n\n");
- else
- {
- fprintf(stdout, "Must change every %d weeks.\n", max_age);
- fprintf(stdout, "May change every %d weeks.\n", min_age);
- fprintf(stdout, "Last changed in week starting %s\n\n",
- ctime(&time));
- }
- }
-
- endpwent();
- } /* End of main() */
- #endif /* EXAMPLE */
-